package cc.autoapi.pucong.auto.flow.provider.node.manager;


import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.DataTypeEnum;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.task.AbstractTask;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.task.TaskFactory;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.utils.DataValueUtils;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.utils.JythonUtils;
import cc.autoapi.pucong.auto.flow.core.root.exception.AutoFlowException;
import cc.autoapi.pucong.auto.flow.core.root.selfenum.CommonBoolenEnum;
import cc.autoapi.pucong.auto.flow.core.root.utils.UUID;
import cc.autoapi.pucong.auto.flow.persistence.po.node.NodeInfoPo;
import cc.autoapi.pucong.auto.flow.persistence.po.sys.GroupInfoPo;
import cc.autoapi.pucong.auto.flow.persistence.repository.node.NodeInfoService;
import cc.autoapi.pucong.auto.flow.persistence.utils.UserRequest;
import cc.autoapi.pucong.auto.flow.provider.group.service.GroupInfoService;
import cc.autoapi.pucong.auto.flow.provider.node.entity.NodeInfoConvert;
import cc.autoapi.pucong.auto.flow.provider.node.entity.dto.*;
import cc.autoapi.pucong.auto.flow.provider.node.entity.qo.NodeInfoQo;
import cc.autoapi.pucong.auto.flow.provider.node.entity.vo.NodeInfoDetailVo;
import cc.autoapi.pucong.auto.flow.provider.node.entity.vo.NodeParamsJsTestVo;
import cc.autoapi.pucong.auto.flow.provider.node.entity.vo.NodeParamsTestVo;
import cc.autoapi.pucong.auto.flow.provider.node.entity.vo.NodeTreeVo;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author pucong
 * @description 节点信息 managerService 实现类
 * @create 2024-09-23
 */
@Service
@Slf4j
public class NodeInfoManager {

    @Resource
    private NodeInfoService nodeInfoService;

    @Resource
    private GroupInfoService groupInfoService;

    public List<NodeTreeVo> getList(NodeInfoQo qo) {
        List<NodeInfoPo> nodeInfos = nodeInfoService.list(qo.getNodeName(), qo.getGroupId(), qo.getWhetherEnable());
        List<NodeTreeVo> nodeInfoVos = new ArrayList<>();
        // 获取分组信息
        if (nodeInfos.size() > 0) {
            List<String> groupIds = nodeInfos.stream().map(NodeInfoPo::getGroupId).collect(Collectors.toList());
            List<GroupInfoPo> groupInfos = groupInfoService.listByIds(groupIds);
            for (GroupInfoPo groupInfo : groupInfos) {
                NodeTreeVo vo = new NodeTreeVo();
                vo.setUuid(groupInfo.getUuid());
                vo.setNodeName(groupInfo.getName());
                vo.setTreeType(0);
                vo.setParentId("-1");
                vo.setWhetherEnable(CommonBoolenEnum.是);
                vo.setSortIndex(groupInfo.getSortIndex());
                nodeInfoVos.add(vo);
            }
            for (NodeInfoPo nodeInfo : nodeInfos) {
                NodeTreeVo vo = new NodeTreeVo();
                vo.setUuid(nodeInfo.getUuid());
                vo.setNodeIcoId(nodeInfo.getNodeIcoId());
                vo.setNodeName(nodeInfo.getNodeName());
                vo.setNodeCode(nodeInfo.getNodeCode());
                vo.setTreeType(1);
                vo.setParentId(nodeInfo.getGroupId());
                vo.setWhetherEnable(nodeInfo.getWhetherEnable() == 1 ? CommonBoolenEnum.是 : CommonBoolenEnum.否);
                vo.setSortIndex(nodeInfo.getSortIndex());
                nodeInfoVos.add(vo);
            }
        }
        return nodeInfoVos;
    }

    public NodeInfoDetailVo getDetailById(String id) {
        NodeInfoPo nodeInfo = nodeInfoService.getById(id);
        NodeInfoDetailVo nodeInfoVo = NodeInfoConvert.INSTANCE.po2Detailvo(nodeInfo);
        return nodeInfoVo;
    }

    public NodeExeTestVo javaExeTest(NodeExeTestDto dto) {
        String nodeScript = dto.getNodeScript();
        if (StringUtils.isBlank(nodeScript)) {
            throw new AutoFlowException("源码为空，无法执行");
        }
        Date date = new Date();

        // 执行
        JSONObject jsonObjectParams = new JSONObject();
        for (NodeParamsTestVo params : dto.getParamsTestVos()) {
            DataTypeEnum dateType = params.getDateType();
            Object value = DataValueUtils.transDataType(params.getParamCode(), dateType, params.getParamValue());
            jsonObjectParams.put(params.getParamCode(), value);
        }
        jsonObjectParams.put("instanceNodeId", "instanceNodeId");

        Object value = nodeInfoService.javaExeTest(nodeScript, jsonObjectParams);
        Date date2 = new Date();
        NodeExeTestVo vo = new NodeExeTestVo();
        vo.setStatus(true);
        vo.setTime(date2.getTime() - date.getTime());
        vo.setJsonData(value);
        return vo;
    }

    public NodeExeTestVo jsExeTest(NodeExeJsTestDto dto) {
        NodeExeTestVo vo = new NodeExeTestVo();

        String nodeScript = dto.getNodeScript();
        if (StringUtils.isBlank(nodeScript)) {
            throw new AutoFlowException("源码为空，无法执行");
        }
        Date date = new Date();

        String jsScript2 = "function run (params) {\n" + nodeScript + "\n}";

        // 执行
        JSONObject jsonObjectParams = new JSONObject();
        for (NodeParamsJsTestVo params : dto.getParamsTestVos()) {
            DataTypeEnum dateType = params.getDateType();
            Object value = DataValueUtils.transDataType(params.getParamName(), dateType, params.getParamValue());
            jsonObjectParams.put(params.getParamName(), value);
        }
        jsonObjectParams.put("nodeId", "nodeId");
        jsonObjectParams.put("instanceNodeId", "nodeId");
        jsonObjectParams.put("nodeName", "nodeId");

        Object json = nodeInfoService.jsExeTest(jsScript2, jsonObjectParams);

        Date date2 = new Date();
        vo.setStatus(true);
        vo.setTime(date2.getTime() - date.getTime());
        vo.setJsonData(json);
        return vo;
    }

    public NodeExeTestVo pythonExeTest(NodeExeJsTestDto dto) {
        NodeExeTestVo vo = new NodeExeTestVo();

        String python = dto.getNodeScript();
        if (StringUtils.isBlank(python)) {
            throw new AutoFlowException("源码为空，无法执行");
        }
        Date date = new Date();

        // 执行
        Map<PyObject, PyObject> mapObjectParams = new HashMap<>(16);
        for (NodeParamsJsTestVo params : dto.getParamsTestVos()) {
            DataTypeEnum dateType = params.getDateType();
            PyObject pyObject = JythonUtils.toPyObject(dateType, params.getParamValue());
            mapObjectParams.put(new PyString(params.getParamName()), pyObject);
        }
        mapObjectParams.put(new PyString("nodeId"), new PyString("nodeId"));
        mapObjectParams.put(new PyString("instanceNodeId"), new PyString("instanceNodeId"));
        mapObjectParams.put(new PyString("nodeName"), new PyString("nodeName"));
        mapObjectParams.put(new PyString("context"), null);
        String python2 = "def run (params) {\n" + python + "\n}";

        Object json = nodeInfoService.pythonExeTest(python2, mapObjectParams);
        Date date2 = new Date();
        vo.setStatus(true);
        vo.setTime(date2.getTime() - date.getTime());
        vo.setJsonData(json);
        return vo;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String add(NodeInfoAddDto dto) {
        NodeInfoPo nodeInfo = NodeInfoConvert.INSTANCE.dto2po(dto);
        String id = UUID.uuid();
        nodeInfo.setUuid(id);
        nodeInfo.setNodeIcoId("<svg t=\"1727020420280\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"13165\" width=\"32\" height=\"32\"><path d=\"M853.333333 896H320c-23.466667 0-42.666667-19.2-42.666667-42.666667v-128c-29.866667 2.133333-61.866667-4.266667-89.6-21.333333-38.4-25.6-61.866667-68.266667-61.866666-115.2s23.466667-91.733333 64-117.333333c25.6-17.066667 57.6-25.6 87.466666-21.333334v-128c0-23.466667 19.2-42.666667 42.666667-42.666666h128c-4.266667-32 4.266667-64 21.333333-91.733334 25.6-38.4 68.266667-61.866667 115.2-61.866666s91.733333 23.466667 117.333334 64c17.066667 27.733333 25.6 57.6 21.333333 89.6h128c23.466667 0 42.666667 19.2 42.666667 42.666666v196.266667c0 29.866667-32 51.2-59.733334 38.4l-36.266666-14.933333c-17.066667-6.4-42.666667-6.4-55.466667 4.266666-14.933333 10.666667-23.466667 25.6-23.466667 44.8 0 17.066667 8.533333 32 21.333334 42.666667s38.4 10.666667 53.333333 4.266667l38.4-17.066667c27.733333-12.8 59.733333 8.533333 59.733333 38.4V853.333333c4.266667 23.466667-14.933333 42.666667-38.4 42.666667z m-490.666666-85.333333h448v-89.6c-38.4 10.666667-78.933333 4.266667-113.066667-17.066667-38.4-25.6-61.866667-68.266667-61.866667-115.2s23.466667-91.733333 64-117.333333c34.133333-21.333333 72.533333-27.733333 110.933334-19.2V362.666667h-142.933334c-29.866667 0-51.2-32-38.4-59.733334l6.4-14.933333c8.533333-19.2 8.533333-40.533333-4.266666-55.466667-10.666667-14.933333-25.6-23.466667-44.8-23.466666-17.066667 0-32 8.533333-42.666667 21.333333s-10.666667 38.4-4.266667 53.333333l8.533334 17.066667c12.8 27.733333-8.533333 59.733333-38.4 59.733333H362.666667v142.933334c0 29.866667-32 51.2-59.733334 38.4l-12.8-4.266667c-17.066667-6.4-42.666667-6.4-55.466666 4.266667-14.933333 10.666667-23.466667 25.6-23.466667 44.8 0 17.066667 8.533333 32 21.333333 42.666666s38.4 10.666667 53.333334 4.266667l14.933333-6.4c27.733333-12.8 59.733333 8.533333 59.733333 38.4V810.666667z\" fill=\"#297AFF\" p-id=\"13166\"></path></svg>");
        nodeInfo.setWhetherEnable(0);
        nodeInfo.setCreateBy(UserRequest.getLoginUser().getUuid());
        nodeInfo.setCreateTime(new Date());
        Boolean i = nodeInfoService.save(nodeInfo);
        return id;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean updateById(String id, NodeInfoUpdateDto dto) {
        NodeInfoPo nodeInfoUpdate = NodeInfoConvert.INSTANCE.dto2po(dto);
        nodeInfoUpdate.setUuid(id);
        Boolean i = nodeInfoService.updateById(nodeInfoUpdate);
        return i;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean batchDeleteByIds(List<String> ids) {
        Boolean i = nodeInfoService.removeBatchByIds(ids);
        return i;
    }

    public Boolean enabledById(String id) {
        NodeInfoPo nodeInfoUpdate = new NodeInfoPo();
        nodeInfoUpdate.setUuid(id);
        nodeInfoUpdate.setWhetherEnable(1);
        Boolean i = nodeInfoService.updateById(nodeInfoUpdate);
        return i;
    }

    public Boolean disabledById(String id) {
        NodeInfoPo nodeInfoUpdate = new NodeInfoPo();
        nodeInfoUpdate.setUuid(id);
        nodeInfoUpdate.setWhetherEnable(0);
        Boolean i = nodeInfoService.updateById(nodeInfoUpdate);
        return i;
    }

    public Boolean updateNodeIcon(String id, NodeInfoUpdateIconDto dto) {
        NodeInfoPo nodeInfoUpdate = new NodeInfoPo();
        nodeInfoUpdate.setUuid(id);
        nodeInfoUpdate.setNodeIcoId(dto.getNodeIcoId());
        Boolean i = nodeInfoService.updateById(nodeInfoUpdate);
        return i;
    }

    public Boolean updateNodeSourceCode(String id, NodeInfoUpdateCodeDto dto) {
        NodeInfoPo nodeInfoUpdate = new NodeInfoPo();
        nodeInfoUpdate.setUuid(id);
        nodeInfoUpdate.setNodeScript(dto.getNodeScript());
        Boolean i = nodeInfoService.updateById(nodeInfoUpdate);
        return i;
    }

    public String getNodeSvgByCode(String code) {
        AbstractTask task = TaskFactory.getTask(code);
        if (task != null) {
            return task.getTaskSvgIcon();
        }
        return "";
    }
}
